import {ObjectID} from "mongodb";
import {Meta} from "./public/Meta";
import {FuncParse, opType} from "./FuncParse";
import {sdf} from "./public/sdf";


export class GenCode {


    /**
     * 将/替换为_
     * @param url
     * @returns {string}
     */
    static fixUrl(url:string) {
        let ret = "";
        for (let i = 0; i < url.length; i++) {
            if (url[i] == '/') {
                if (i == 0)
                    continue;

                ret += "_";
                continue;
            }

            ret += url[i];
        }
        return ret;
    }

    /**
     * 将_下划线命名法替换为首字母大写驼峰式
     * @param name
     * @returns {string}
     */
    static fixNmaeUpperCase(name:string) {
        let ret = "";
        for (let i = 0; i < name.length; i++) {
            if (name[i] == "_") {
                i++;
                if (i < name.length)
                    ret += name[i].toUpperCase();
                continue;
            }

            ret += name[i];
        }

        return ret;
    }


    /**
     * 读取代码注释
     * @param code
     * @param name
     * @param back
     * @returns {string}
     */
    static readComment(clas:string|Function, name:string, back:number):string {
        if (clas == null)
            return ""

        if (name.length < 1) {
            return "";
        }


        let code = "" + clas;
        if (clas instanceof Function) {
            let par = Meta.getParent(clas);
            for (let m of par) {
                code += "\r\n" + m
            }
        }


        let i = code.indexOf(name);
        if (i < 2)
            return "";

        i -= 2;
        let comment = "";
        FuncParse.parseLexical(code, i, (op, type)=> {
            back--;
            // console.error("op " + op + "   " + back);
            if (back < 0) {
                if (type == opType.comment) {
                    comment = op;
                }
                return false;
            }

            return true;
        }, true);

        return comment.replace(/(?:\r\n|\r|\n| +)/g, ' ');
    }


    /**
     * 解析对象
     * @param resp
     * @param func
     */
    static parseObj(resp:any, func:(name:string, val:any, parentName:string, start:boolean, end:boolean, curObj?:any)=>void) {
        let deepI = 0;

        //类名列表
        let objName = [""];
        //对象列表
        let objStack = [resp];


        while (objStack.length > 0) {

            //当前对象
            let curObj = objStack[0];

            //类名
            let curName = objName[0];

            func(curName, curObj, curName, true, false, curObj);

            for (let name in curObj) {

                let val = curObj[name];

                if (typeof  val == "string" || typeof  val == "number" || val instanceof ObjectID || val == null) {
                    func(name, val, curName, false, false, curObj);
                }
                else if (val instanceof Array) {
                    //遍历嵌套数组
                    for (let arrObj = val as any[]; ;) {
                        if (arrObj.length > 0) {
                            arrObj = arrObj[0];
                            if (arrObj instanceof Array)
                                continue;
                            if (typeof arrObj == "object" && !(arrObj instanceof ObjectID)) {
                                objStack.push(arrObj);
                                objName.push(name);
                                break;
                            }
                            else {

                                break;
                            }

                        }
                        else {
                            let type = Meta.getArrayType(curObj, name);
                            if (!type)
                                type = sdf.getArrayType(val);
                            if (type) {
                                arrObj.push(new type());
                                continue;
                            }
                            break;
                        }

                    }

                    func(name, val, curName, false, false, curObj);
                }
                else if (typeof val == "object") {
                    objStack.push(val);
                    objName.push(name);

                    func(name, val, curName, false, false, curObj);
                }
            }
            func(curName, null, curName, false, true, curObj);

            objStack.splice(0, 1);
            objName.splice(0, 1);

        }


    }


}